home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr26 / netprog.zip / NETPROG.TAR / rcmd / ruserok.c < prev   
C/C++ Source or Header  |  1989-12-17  |  10KB  |  317 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. /*
  19.  * From the file: "@(#)rcmd.c   5.20 (Berkeley) 1/24/89";
  20.  */
  21.  
  22. /*
  23.  * Validate a remote user.  This function is called on the server's system.
  24.  *
  25.  * Called by: /etc/rshd (the server for the rcmd() function);
  26.  *          /bin/login (when invoked by /etc/rlogind for a remote login).
  27.  */
  28.  
  29. #include    <sys/types.h>
  30. #include    <sys/param.h>
  31. #include    <sys/stat.h>
  32. #include    <stdio.h>
  33. #include    <pwd.h>
  34. #include    <ctype.h>
  35.  
  36. int    _check_rhosts_file = 1;    /* set to 0 by rlogind and rshd, if they're
  37.                    invoked with -l option */
  38.  
  39. int                    /* return 0 if OK, else -1 */
  40. ruserok(rhost, superuser, cliuname, servuname)
  41. char    *rhost;          /* "hostname" or "hostname.domain" of client; obtained
  42.              by caller: gethostbyaddr( getpeername( ) ) */
  43. int    superuser;    /* 1 if caller wants to be root on this (server's) sys */
  44. char    *cliuname;    /* username on client's system */
  45. char    *servuname;   /* username on this (server's) system */
  46. {
  47.     register int    first, hostlen;
  48.     register char    *src, *dst;
  49.     char        clihostname[MAXHOSTNAMELEN];
  50.     register FILE    *hostfp;
  51.  
  52.     /*
  53.      * First make a copy of the client's host name, remembering if
  54.      * it contains a domain suffix.  Also convert everything to
  55.      * lower case.
  56.      */
  57.  
  58.     src = rhost;
  59.     dst = clihostname;
  60.     hostlen = -1;
  61.     while (*src) {
  62.         if (*src == '.') {
  63.             /*
  64.              * When we hit a period, check if it's the first period,
  65.              * and if so, save the length of the host name
  66.              * (i.e., everything up to the first period).
  67.              */
  68.  
  69.             if (hostlen == -1)
  70.                 hostlen = src - rhost;
  71.             *dst++ = *src++;
  72.         } else {
  73.             *dst++ = isupper(*src) ? tolower(*src++) : *src++;
  74.         }
  75.     }
  76.     *dst = '\0';
  77.  
  78.     /*
  79.      * If the caller wants to be the superuser on this system, then all
  80.      * we check is the file "/.rhosts".  Else we'll check the file
  81.      * "/etc/hosts.equiv" the first time through the loop below.
  82.      */
  83.  
  84.     hostfp = superuser ? (FILE *) 0 : fopen("/etc/hosts.equiv", "r");
  85.  
  86.     first = 1;
  87. again:
  88.     if (hostfp) {
  89.         if (_validuser(hostfp, clihostname, servuname, cliuname,
  90.                                 hostlen) == 0) {
  91.             fclose(hostfp);        /* all OK, close file */
  92.             return(0);        /* we're done */
  93.         }
  94.         fclose(hostfp);        /* not valid, close file */
  95.     }
  96.     if (first == 1 && (_check_rhosts_file || superuser)) {
  97.         struct stat    statbuff;
  98.         struct passwd    *pwd;
  99.         char        buff[MAXPATHLEN];
  100.  
  101.         first = 0;
  102.         if ( (pwd = getpwnam(servuname)) == NULL)
  103.             return(-1);    /* no password file entry */
  104.  
  105.         strcpy(buff, pwd->pw_dir); /* get home directory of servuname */
  106.         strcat(buff, "/.rhosts");  /* will be "//.rhosts" if root */
  107.         if ( (hostfp = fopen(buff, "r")) == NULL)
  108.             return(-1);    /* can't open user's .rhosts file */
  109.  
  110.         /*
  111.          * If the user is not root, then the owner of the .rhosts file
  112.          * has to be the user.  Also, the .rhosts file can't be
  113.          * writable by anyone other than the owner.
  114.          */
  115.  
  116.         if ((fstat(fileno(hostfp), &statbuff) < 0) ||
  117.             (statbuff.st_uid != 0 && statbuff.st_uid != pwd->pw_uid) ||
  118.             (statbuff.st_mode & 022)) {
  119.             fclose(hostfp);
  120.             return(-1);
  121.         }
  122.         goto again;    /* go and call _validuser() */
  123.     }
  124.     return(-1);        /* not a valid user */
  125. }
  126.  
  127. /*
  128.  * Validate a user.  This is called from the ruserok() function above, and
  129.  * directly by the lpd server.  When the lpd server calls us, it sets both
  130.  * "servuname" and "cliuname" to point to the same string, so that they'll
  131.  * compare as equal.
  132.  */
  133.  
  134. int                /* return 0 if valid, else -1 */
  135. _validuser(hostfp, clihostname, servuname, cliuname, hostlen)
  136. FILE    *hostfp;    /* FILE pointer to "/etc/hosts.equiv", ".rhosts",
  137.                or "/etc/hosts.lpd" file */
  138. char    *clihostname;    /* client's "hostname" or "hostname.domain" */
  139. char    *servuname;    /* username on this (server's) system */
  140. char    *cliuname;    /* username on client's system */
  141. int    hostlen;    /* -1 if "hostname"; else its "hostname.domain" and this
  142.                is the #chars in hostname */
  143. {
  144.     register char    *ptr;
  145.     char        *user;
  146.     char        hostname[MAXHOSTNAMELEN];
  147.  
  148.     /*
  149.      * Read and process each line of the file.
  150.      */
  151.  
  152.     while (fgets(hostname, sizeof(hostname), hostfp)) {
  153.         ptr = hostname;
  154.         while (*ptr != '\n' && *ptr != ' ' &&
  155.                *ptr != '\t' && *ptr != '\0') {
  156.                 *ptr = isupper(*ptr) ? tolower(*ptr) : *ptr;
  157.                 ptr++;
  158.         }
  159.         if (*ptr == ' ' || *ptr == '\t') {
  160.             /*
  161.              * If the host name was terminated with either a blank
  162.              * or a tab, then there's a user name following.
  163.              * We set "user" to point to the first character of
  164.              * this user name.
  165.              */
  166.  
  167.             *ptr++ = '\0';        /* null terminate host name */
  168.  
  169.             while (*ptr == ' ' || *ptr == '\t')
  170.                 ptr++;        /* skip over the white space */
  171.             user = ptr;
  172.  
  173.             /*
  174.              * We have to skip to the end of the user name, so that
  175.              * we can assure it's terminated with a null byte.
  176.              */
  177.  
  178.             while (*ptr != '\n' && *ptr != ' ' &&
  179.                    *ptr != '\t' && *ptr != '\0')
  180.                     ptr++;
  181.         } else {
  182.             /*
  183.              * If there's not a user name in the line from the file,
  184.              * we have "user" point to the null byte that terminates
  185.              * the host name.  This means the user name is a C null
  186.              * string.  This fact is used in the strcmp() below.
  187.              */
  188.  
  189.             user = ptr;
  190.         }
  191.         *ptr = '\0';    /* null terminate host name or user name */
  192.  
  193.         /*
  194.          * If the host fields match (_checkhost() function below), then:
  195.          * (a) if a user name appeared in the line from the file that
  196.          *     we processed above, then that user name has to equal the
  197.          *     user name on the server (servuname).
  198.          * (b) if no user name appeared in the line from the file, then
  199.          *     the user name on the server (servuname) has to equal the
  200.          *     user name on the client (cliuname).
  201.          */
  202.  
  203.         if (_checkhost(clihostname, hostname, hostlen) &&
  204.             (strcmp(cliuname, *user ? user : servuname) == 0) )
  205.             return(0);    /* OK */
  206.  
  207.         /* else read next line of file */
  208.     }
  209.     return(-1);        /* end-of-file, no match found */
  210. }
  211.  
  212. /*
  213.  * Validate only the client's host name.
  214.  * We compare the client's host name, either "hostname" or "hostname.domain"
  215.  * to the host name entry from a line of the /etc/hosts.equiv or .rhosts file.
  216.  * If there is not a domain qualifier in the client's host name, then things
  217.  * are simple: the client's hostname has to exactly equal the hostname
  218.  * field from the line of the file.
  219.  *
  220.  * However, domains complicate this routine.  See the comments below.
  221.  */
  222.  
  223. static char    locdomname[MAXHOSTNAMELEN + 1];
  224. static char    *locdomptr = NULL;
  225. static int    locdomerror = 0;
  226.  
  227. static int                    /* return 1 if OK, else 0 */
  228. _checkhost(clihostname, hostfield, hostlen)
  229. char    *clihostname;    /* client's "hostname" or "hostname.domain" */
  230. char    *hostfield;    /* the hostname field from the file */
  231. int    hostlen;    /* -1 if no ".domain", else length of "hostname" */
  232. {
  233.     register char    *ptr;
  234.     char        *index();
  235.  
  236.     /*
  237.      * If there isn't a domain qualifier on the client's hostname,
  238.      * then just compare the host names.  They have to be equal
  239.      * to return 1 (OK).
  240.      */
  241.  
  242.     if (hostlen == -1)
  243.         return(strcmp(clihostname, hostfield) == 0);    /* 1 if equal */
  244.  
  245.     /*
  246.      * There is a domain qualifier on the client's hostname.  If the
  247.      * client's hostname (everything up to the first period) doesn't equal
  248.      * the host name in the file, then return an error now.
  249.      */
  250.  
  251.     if (strncmp(clihostname, hostfield, hostlen) != 0)
  252.         return(0);    /* not a valid host */
  253.  
  254.     /*
  255.      * If the client's "hostname.domain" exactly equals the entry from
  256.      * the file, then return OK now.
  257.      */
  258.  
  259.     if (strcmp(clihostname, hostfield) == 0)
  260.         return(1);    /* valid host */
  261.  
  262.     /*
  263.      * If the entry in the file is not "hostname." (a terminating period,
  264.      * without a domain name), then return an error now.
  265.      */
  266.  
  267.     if (*(hostfield + hostlen) != '\0')
  268.         return(0);    /* not a valid host */
  269.  
  270.     /*
  271.      * When we get here, the entry from the file is "hostname.",
  272.      * meaning "use the local domain" as the domain.
  273.      * If we've already tried to obtain the local domain and encountered
  274.      * an error, return an error.
  275.      */
  276.  
  277.     if (locdomerror == 1)
  278.         return(0);    /* couldn't get local domain name */
  279.  
  280.     if (locdomptr == NULL) {
  281.         /*
  282.          * Try once to get the local domain name.
  283.          */
  284.  
  285.         if (gethostname(locdomname, sizeof(locdomname)) == -1) {
  286.             locdomerror = 1;    /* system call error */
  287.             return(0);        /* return not valid */
  288.         }
  289.         locdomname[MAXHOSTNAMELEN] = '\0';
  290.                 /* assure it's null terminated */
  291.  
  292.         /*
  293.          * We got the "localhostname.localdomainmame" string from the
  294.          * kernel.  Save the pointer to the "locdomainmame" part,
  295.          * then assure it's lower case.
  296.          */
  297.  
  298.         if ( (locdomptr = index(locdomname, '.')) == NULL) {
  299.             locdomerror = 1;    /* humm, no period */
  300.             return(0);        /* return not valid */
  301.         }
  302.  
  303.         for (ptr = ++locdomptr; *ptr; ptr++)
  304.             if (isupper(*ptr))
  305.                 *ptr = tolower(*ptr);
  306.     }
  307.  
  308.     /*
  309.      * We know the host names are identical, and the entry in the file was
  310.      * "hostname.".  So now we compare the client's domain with the local
  311.      * domain, and if equal, all is OK.
  312.      */
  313.  
  314.     return(strcmp(locdomptr, clihostname + hostlen + 1) == 0);
  315.                     /* returns 1 if equal, 0 otherwise */
  316. }
  317.